package com.erp.service;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.activiti.engine.IdentityService;
import org.activiti.engine.identity.Group;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import com.erp.dao.DepartmentDAO;
import com.erp.dao.RoleDAO;
import com.erp.dao.UserDAO;
import com.erp.domain.TDepartment;
import com.erp.domain.TRole;
import com.erp.domain.TUser;
import com.erp.dto.IpLocation;
import com.erp.dto.Page;
import com.erp.dto.Privilege;
import com.erp.dto.Role;
import com.erp.dto.User;
import com.erp.util.IpUtil;

@Service(value = "userService")
@Transactional
public class UserService {

	private static final String DEFAULT_PASSWORD = "12345";

	@Resource(name = "userDAO")
	private UserDAO userDAO;

	@Resource(name = "roleDAO")
	private RoleDAO roleDAO;

	@Resource(name = "departmentDAO")
	private DepartmentDAO departmentDAO;

	/**
	 * ACT_ID_*表操作接口
	 */
	@Resource(name = "identityService")
	private IdentityService identityService;

	/**
	 * 获取数据库里所有用户列表
	 * 
	 * @return
	 */
	public List<User> listAll() {
		List<TUser> TUserList = new ArrayList<TUser>(0);
		List<User> userList = new ArrayList<User>(0);
		TUserList = userDAO.listAll();
		if (TUserList != null) {
			for (int i = 0; i < TUserList.size(); i++) {
				userList.add(new User(TUserList.get(i)));
			}
		}
		return userList;
	}

	/**
	 * 获取分页后的用户列表
	 * 
	 * @return
	 */
	public List<User> getPagedList(Page page) {
		// 开始页码
		int from = (page.getPageIndex() - 1) * page.getPageSize();
		List<User> userList = null;
		int totalRecord = userDAO.countAll().intValue();
		page.setTotalRecord(totalRecord);
		int totalPage = 1;
		if (totalRecord > 0) {
			userList = new ArrayList<User>();
			List<TUser> tUserList;
			tUserList = userDAO.paging(from, page.getPageSize());
			// 设置总页数
			totalPage = totalRecord % (page.getPageSize()) > 0 ? totalRecord
					/ (page.getPageSize()) + 1 : totalRecord
					/ (page.getPageSize());

			for (int i = 0; i < tUserList.size(); i++) {
				userList.add(new User(tUserList.get(i)));
			}
		}
		page.setTotalPage(totalPage);
		return userList;
	}

	/**
	 * 登录操作，若成功则设置登录的时间、IP、地址，失败则返回null
	 * 
	 * @param user
	 *            包含用户的账号和密码
	 * @param encodedPWD
	 *            是不是已经编码过的密码，未编码则为false
	 * @return
	 */
	public User login(User user, boolean encodedPWD) {
		String name = user.getName();
		String password = user.getPassword();
		String ip = user.getIp();
		String location = null;
		// 如果是没加密过的密码则先加密
		if (!encodedPWD) {
			password = DigestUtils.md5DigestAsHex(password.getBytes());
		}
		String sql = "select user from TUser user where name='" + name
				+ "' and password='" + password + "' order by user.id";
		TUser tUser = userDAO.get(sql);
		if (tUser != null) {
			tUser = userDAO.getById(tUser.getId());
			tUser.setLoginTime(user.getLoginTime());
			// 获取上次登录地点
			location = tUser.getLoginLocation();
			if (!user.getIp().equals(tUser.getIp())) {
				tUser.setIp(ip);
				// 通过ACE的API获取IP所在地理位置并存入数据库
				// TODO 修改type改变访问外网的方式
				IpLocation ipLocation = IpUtil.getIpLocationByIp(ip,
						IpUtil.DIRECT);
				tUser.setLoginLocation(ipLocation != null ? ipLocation
						.getCity() : "未知地区");
			}
			user = new User(tUser);
			// 设置上次登录地点
			user.setLoginLocation(location != null ? location : "首次登录");
			return user;
		} else {
			return null;
		}
	}

	/**
	 * 根据用户的角色列表获取该用户拥有的所有权限
	 * 
	 * @param roleList
	 *            用户角色列表
	 * @return 用户权限列表
	 */
	public List<Privilege> getUserPrivilege(List<Role> roles) {
		List<Privilege> userPrivilegeList = new ArrayList<Privilege>(0);
		// 一个用户只有一个角色
		if (roles.size() == 1) {
			for (int i = 0; i < roles.get(0).getPrivilegeList().size(); i++) {
				userPrivilegeList.add(roles.get(0).getPrivilegeList().get(i));
			}
		} else if (roles.size() > 1) {
			// 一个用户多个角色
			// 循环遍历每个角色
			for (int i = 0; i < roles.size(); i++) {
				List<Privilege> rolePrivilegeList = roles.get(i)
						.getPrivilegeList();
				// 循环角色权限列表
				for (int j = 0; j < rolePrivilegeList.size(); j++) {
					int count = 0;
					// 用户权限列表是否已存在此权限
					for (int k = 0; k < userPrivilegeList.size(); k++) {
						if (userPrivilegeList.get(k).equals(
								rolePrivilegeList.get(j))) {
							count++;
						}
					}
					// 不存在则将角色权限添加到用户权限列表
					if (count == 0) {
						userPrivilegeList.add(rolePrivilegeList.get(j));
					}
				}
			}
		}
		return userPrivilegeList;
	}

	private Integer add(User user) {
		TUser tUser = new TUser(user);

		List<TRole> tRoles = new ArrayList<TRole>();
		List<Role> roles = user.getRoles();
		for (Role role : roles) {
			tRoles.add(new TRole(role));
		}
		tUser.settRoles(tRoles);

		return (Integer) userDAO.save(tUser);
	}

	/**
	 * 保存用户的同时同步到Activiti的ACT_ID_USER表中
	 * 
	 * @param user
	 * @param synToActiviti
	 *            true表示同步到Activiti
	 */
	public void add(User user, boolean synToActiviti) {

		user.setId(this.add(user));// 将用户写入t_user表
		// 同步添加用户信息到Activiti
		if (synToActiviti) {
			synToActiviti(user);
		}

	}

	/**
	 * 把用户同步添加或更新到Activiti中
	 * 
	 * @param user
	 */
	public void synToActiviti(User user) {
		if (user.getId() != null) {
			String userId = user.getId().toString();
			List<org.activiti.engine.identity.User> activitiUsers = identityService
					.createUserQuery()//
					.userId(userId)//
					.list();//
			// TODO 判断Activiti中是否已存在该ID的用户
			org.activiti.engine.identity.User activitiUser = null;
			if (activitiUsers.size() == 1) {// 若存在该用户则更新用户信息

				// 获取数据库里的用户
				activitiUser = activitiUsers.get(0);

				// 删除用户原来的membership（用户和用户组的关联）
				List<Group> activitiGroups = identityService.createGroupQuery()//
						.groupMember(userId)//
						.list();//
				for (Group group : activitiGroups) {
					identityService.deleteMembership(userId, group.getId());
				}

			} else if (activitiUsers.size() == 0) {// 若不存在该用户
				// activiti里新建用户
				activitiUser = identityService.newUser(userId);
			}

			activitiUser.setFirstName(user.getName());
			activitiUser.setLastName("");
			activitiUser.setPassword(user.getPassword());
			activitiUser.setEmail(user.getEmail());
			identityService.saveUser(activitiUser);// 相当于saveOrUpdate

			// 添加新的membership
			for (Role role : user.getRoles()) {
				identityService.createMembership(userId, role.getSign());
			}
		}
	}

	public void delete(User user) {
		userDAO.deleteById(user.getId());
	}

	public User getUserById(Integer id) {
		return new User(userDAO.getById(id));
	}

	/**
	 * 通过姓名获取用户
	 * 
	 * @param name
	 * @return
	 */
	@Deprecated
	public User getUserByName(String name) {
		TUser tUser = userDAO.get("from TUser user where name='" + name + "' ");
		return new User(tUser);
	}

	private User update(User user) {

		TUser tUser = userDAO.getById(user.getId());
		tUser.settDepartment(new TDepartment(user.getDepartment()));
		tUser.setName(user.getName());
		tUser.setSex(user.getSex());
		tUser.setPhone(user.getPhone());
		tUser.setEmail(user.getEmail());
		tUser.setDescription(user.getDescription());

		List<TRole> tRoles = new ArrayList<TRole>();
		List<Role> roles = user.getRoles();
		if (roles != null) {
			for (Role role : roles) {
				tRoles.add(new TRole(role));
			}
		}
		tUser.settRoles(tRoles);

		return new User(tUser);
	}

	/**
	 * 更新t_user时同步更新Activiti的ACT_ID_USER表
	 * 
	 * @param user
	 * @param synToActiviti
	 */
	public void update(User user, boolean synToActiviti) {

		user = this.update(user);
		// 同步更新用户信息到Activiti
		if (synToActiviti) {
			synToActiviti(user);
		}
	}

	public String initPassword(User user) {
		TUser tUser = userDAO.getById(user.getId());
		String password = DigestUtils.md5DigestAsHex(DEFAULT_PASSWORD
				.getBytes());
		tUser.setPassword(password);
		userDAO.update(tUser);
		return password;
	}

	public String midifyPassword(User user) {
		TUser tUser = userDAO.getById(user.getId());
		String password = DigestUtils.md5DigestAsHex(user.getPassword()
				.getBytes());
		tUser.setPassword(password);
		userDAO.update(tUser);
		return password;
	}

	@Deprecated
	public boolean checkPassword(User user) {
		TUser tUser = userDAO.getById(user.getId());
		if (tUser.getPassword().equals(user.getPassword())) {
			return true;
		} else {
			return false;
		}
	}

}
